<?
/*
Galaxy
Author:McFog
*/
defined('IN GALAXY') or exit('McFog');

function __autoload($name) {
	$name = str_replace(array('/', '\\'), '', $name);
	galaxy::load($name);
}

class galaxy {
	var $config, $db, $bbinfo;
	var $galx_uid = 0, $galx_username = NULL;
	static $instance = NULL;
	function __construct() {
		if(self::$instance===NULL) {
			self::$instance = $this;
		} else {
			self::halt("Duplicate galaxy instance");
			//unset(self::$instance);
			//self::$instance = $this;
		}
		$this->init_data();
		$this->init_db();
		$this->init_const();
		$this->init_env();
		$this->init_user();
	}
	static function halt($msg) {
		echo("<h3>Galaxy Core Error</h3><p>$msg</p><pre>");
		debug_print_backtrace();
		exit;
	}
	
	static function getInstance() {
		if(self::$instance===NULL) {
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	static function load($name) {
		if(substr($name, 0, 6)=='model_') {
			require ROOT.'model/'.substr($name,6).'.php';
		} elseif(substr($name, 0, 5)=='view_') {
			require ROOT.'view/'.substr($name,5).'.php';
		} else {
			require ROOT.'lib/'.$name.'.php';
		}
	}
	//initial
	function init_data() {
		$this->config = include(DATADIR.'config.php');
		$this->bbinfo = include(DATADIR.'bbinfo.php');
		$this->setting = include(DATADIR.'setting.php');
	}
	function init_db() {
		$cfg = &$this->config;
		$this->db = new model_db;
		$this->db->connect($cfg['dbhost'], $cfg['dbuser'], $cfg['dbpass'],
			$cfg['charset'] , $cfg['dbname'], $cfg['dbpconnect']);
	}
	function init_const() {
		define('_TPLPath_', ROOT.'shell/default/');
		define('_TPLCacheLimit_', 0);
		define('_TPLCachePath_', CACHEDIR.'tpl/');

    if( !defined('EXTR_PREFIX_ALL') ) define('EXTR_PREFIX_ALL', 3);
    if( !defined('EXTR_PREFIX_INVALID') ) define('EXTR_PREFIX_INVALID', 4);
    if( !defined('EXTR_IF_EXISTS') ) define('EXTR_IF_EXISTS', 5);
    if( !defined('EXTR_PREFIX_IF_EXISTS') ) define('EXTR_PREFIX_IF_EXISTS', 6);
    if( !defined('EXTR_REFS') ) define('EXTR_REFS', 256);
	}
	function init_env() {
		//time
		$timestamp = time();
		$timeoffset = 8;
		$timenow = array('time' => gmdate($this->setting['dateformat'].' '.$this->setting['timeformat'], $timestamp + 3600 * $timeoffset),
			'offset' => ($timeoffset >= 0 ? ($timeoffset == 0 ? '' : '+'.$timeoffset) : $timeoffset));
			
		//ip
		if($_SERVER['HTTP_CLIENT_IP'] && strcasecmp($_SERVER['HTTP_CLIENT_IP'], 'unknown')) {
			$onlineip = $_SERVER['HTTP_CLIENT_IP'];
		} elseif($_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], 'unknown')) {
			$onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
		} elseif($_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
			$onlineip = $_SERVER['REMOTE_ADDR'];
		} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
			$onlineip = $_SERVER['REMOTE_ADDR'];
		}
		preg_match("/[\d\.]{7,15}/", $onlineip, $onlineipmatches);
		$onlineip = $onlineipmatches[0] ? $onlineipmatches[0] : 'unknown';
		unset($onlineipmatches);

		self::extract_to(get_defined_vars(), $_ENV, EXTR_SKIP);
	}
	function init_user() {
		$auth = self::gcookie('auth');
		if(!empty($auth)) {
			list($galx_uid, $galx_username) = explode("\t", self::authcode( $auth, 'DECODE' ));
		} else {
			$galx_uid = $galx_username = '';
		}
		self::extract_to(get_defined_vars(), $this);
	}
	
	//global functions
	static function showmessage($msg, $fwd='') {
		$v = new view_message($msg, $fwd);
		$v->show();
		exit;
	}
	
	static function showtemplate($tplname, $data=array(), $userpack = 'templates.lang.php') {
		$v = new view_common($tplname, $data, $userpack);
		$v->show();
		exit;
	}

  static function extract_to( &$arr, &$to, $type=EXTR_OVERWRITE, $prefix=false ){
        if( $type & EXTR_REFS ) {
        	$type ^= EXTR_REFS;
        	$ref = true;
        } else {
        	$ref = false;
        }
      
      if( !is_array( $arr ) ) return trigger_error("extract_to(): First argument should be an array", E_USER_WARNING );
      
      if( is_array( $to ) ) $t=0;
      else if( is_object( $to ) ) $t=1;
      else return trigger_error("extract_to(): Second argument should be an array or object", E_USER_WARNING );
      
      if( $type==EXTR_PREFIX_SAME || $type==EXTR_PREFIX_ALL || $type==EXTR_PREFIX_INVALID || $type==EXTR_PREFIX_IF_EXISTS )
          if( $prefix===false ) return trigger_error("extract_to(): Prefix expected to be specified", E_USER_WARNING ); 
          else $prefix .= '_';
      
      $i=0;
      foreach( $arr as $key=>$val ){
          $nkey = $key;
          $isset = $t==0 ? isset( $to[$key] ) : isset( $to->$key );
          
          if( ( $type==EXTR_SKIP && $isset ) 
              || ( $type==EXTR_IF_EXISTS && !$isset ) )
                  continue;
          
          else if( ( $type==EXTR_PREFIX_SAME && $isset )
              || ( $type==EXTR_PREFIX_ALL )
              || ( $type==EXTR_PREFIX_INVALID && !preg_match( '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', $key ) ) )
                  $nkey = $prefix.$key;
                  
          else if( $type==EXTR_PREFIX_IF_EXISTS )
              if( $isset ) $nkey = $prefix.$key;
              else continue;

          if( !preg_match( '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', $nkey ) ) continue;
          
          if( $t==1 )
              if( $ref ) $to->$nkey = &$arr[$key];
              else $to->$nkey = $val;
          else 
              if( $ref ) $to[$nkey] = &$arr[$key];
              else $to[$nkey] = $val;
          
          $i++;
      }
      
      return $i;
  }
  
  static function debug($msg) {
		$trace = debug_backtrace();
		trigger_error("$msg: $name in <b>{$trace[0][file]}</b> on line <b>{$trace[0][line]}</b> (not)", E_USER_NOTICE);
		return null;
  }
  
	static function authcode($string, $operation = 'DECODE', $expiry = 0, $key = '') {
	
		$ckey_length = 4;
	
		$key = md5($key ? $key : UC_KEY);
		$keya = md5(substr($key, 0, 16));
		$keyb = md5(substr($key, 16, 16));
		$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
	
		$cryptkey = $keya.md5($keya.$keyc);
		$key_length = strlen($cryptkey);
	
		$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
		$string_length = strlen($string);
	
		$result = '';
		$box = range(0, 255);
	
		$rndkey = array();
		for($i = 0; $i <= 255; $i++) {
			$rndkey[$i] = ord($cryptkey[$i % $key_length]);
		}
	
		for($j = $i = 0; $i < 256; $i++) {
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}
	
		for($a = $j = $i = 0; $i < $string_length; $i++) {
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}
	
		if($operation == 'DECODE') {
			if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
				return substr($result, 26);
			} else {
				return '';
			}
		} else {
			return $keyc.str_replace('=', '', base64_encode($result));
		}
	
	}

	static function gaddslashes($string, $force = 0, $strip = FALSE) {
		defined('MAGIC_QUOTES_GPC') or define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
		if(!MAGIC_QUOTES_GPC || $force) {
			if(is_array($string)) {
				foreach($string as $key => $val) {
					$string[$key] = self::gaddslashes($val, $force, $strip);
				}
			} else {
				$string = addslashes($strip ? stripslashes($string) : $string);
			}
		}
		return $string;
	}
	
	static function gcookie($name, $value='', $life=86400000) {
		@extract(self::getInstance()->config);
		$name = $cookiepre.$name;
		if(func_num_args()==1) return $_COOKIE[$name];
		setcookie($name, $value,
			$_ENV['timestamp'] + $life, $cookiepath,
			$cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0);
	}
}
?>